{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.1 为什么要用Go语言？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 直接编译为二进制，没有虚拟化损失\n",
    "- 自带运行环境，无需处理 GC 问题\n",
    "- 一次编码可以适用多种平台\n",
    "- 超强的并发支持与并发易用性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Language | 一次编码 | 一次编译 | 不需要运行环境 | 没有虚拟化损失 | 不需要自行处理GC | 面向对象 | 非常易用的并发能力 |\n",
    "|---------|-------|-------|------------|-----------|--------------|-------|------------|\n",
    "| C       | X     | ✓     | X          | ✓         | X            | X     | X          |\n",
    "| C++     | X     | ✓     | X          | ✓         | X            | ✓     | X          |\n",
    "| Java    | ✓     | X     | ✓          | X         | ✓            | ✓     | X          |\n",
    "| JavaScript | ✓   | O     | ✓          | X         | ✓            | ✓     | X          |\n",
    "| Go      | ✓     | X     | ✓          | ✓         | ✓            | ✓     | ✓          |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.2 何为Runtime?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运行环境\n",
    "- Java: Virtual Machine\n",
    "- JS:浏览器\n",
    "- Go: 并不是虚拟机, 作为程序的一部分; GC, 协程调度"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.3 Go程序是如何编译的？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "go: creating new go.mod: module howtocompile\n",
      "go: to add module requirements and sums:\n",
      "\tgo mod tidy\n"
     ]
    }
   ],
   "source": [
    "! cd ./3.3 && go mod init howtocompile "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! cd ./3.3 && go build -n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- import config\n",
    "```shell\n",
    "# import config\n",
    "packagefile fmt=/home/ningliu/.cache/go-build/1f/1f4252d05f307cafa73df613b7bbcd5be39634305e96b04f5c0b0ebe9ddc3e31-d\n",
    "packagefile runtime=/home/ningliu/.cache/go-build/f5/f5f72d3edd7c69903cb183a950ed24b831c0bbac8beffc77f619cd8508be8b3e-d\n",
    "```\n",
    "\n",
    "``\n",
    "\n",
    "- `/usr/local/go/pkg/tool/linux_amd64/compile`\n",
    "\n",
    "- `/usr/local/go/pkg/tool/linux_amd64/link`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "词法分析: 将源代码翻译成Token(最小语义结构)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "句法分析: 将Token序列处理为语法树(SST)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "语义分析: 类型检查, 类型推断, 类型是否匹配, 函数内联, 逃逸分析"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "中间码生成(SSA): 平台无关的\"汇编\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "# runtime\n",
      "dumped SSA for main,1 to /mnt/d/dev_learn/learnlibrary_notes/Redis/576-go-redis/3/3.3/ssa.html\n",
      "# howtocompile\n",
      "dumped SSA for main,1 to ./ssa.html\n"
     ]
    }
   ],
   "source": [
    "! cd ./3.3 && export GOSSAFUNC=\"main\" && go build"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "代码优化"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "机器码生成: 生成Plan9汇编, 编译为机器码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! cd ./3.3 && go build -gcflags -S helloworld.go"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "链接"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.4 Go程序是如何运行的?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Go程序的入口"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://go.dev/src/runtime/, `rt0_平台.s`, [rt0_linux_amd64.s](https://go.dev/src/runtime/rt0_linux_amd64.s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c\n",
    "// Copyright 2009 The Go Authors. All rights reserved.\n",
    "// Use of this source code is governed by a BSD-style\n",
    "// license that can be found in the LICENSE file.\n",
    "\n",
    "#include \"textflag.h\"\n",
    "\n",
    "TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8\n",
    "\tJMP\t_rt0_amd64(SB)\n",
    "\n",
    "TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0\n",
    "\tJMP\t_rt0_amd64_lib(SB)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://go.dev/src/runtime/asm_amd64.s"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```go\n",
    "// ...\n",
    "\n",
    "// _rt0_amd64 is common startup code for most amd64 systems when using\n",
    "// internal linking. This is the entry point for the program from the\n",
    "// kernel for an ordinary -buildmode=exe program. The stack holds the\n",
    "// number of arguments and the C-style argv.\n",
    "TEXT _rt0_amd64(SB),NOSPLIT,$-8\n",
    "\tMOVQ\t0(SP), DI\t// argc\n",
    "\tLEAQ\t8(SP), SI\t// argv\n",
    "\tJMP\truntime·rt0_go(SB)\n",
    "\n",
    "// ...\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 运行时检测"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 检查各种类型的长度\n",
    "- 检查结构体字段的偏移量\n",
    "- 检查 CAS 操作\n",
    "- 检查指针操作\n",
    "- 检查 atomic 原子操作\n",
    "- 检查栈大小是否是 2 的幂次"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 参数初始化 `runtime.args`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 对命令行中的参数进行处理\n",
    "- 参数数量赋值给 `argc int32`\n",
    "- 参数值复制给 `argv **byte`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 调度器初始化 `runtime.schedinit`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 全局栈空间内存分配\n",
    "- 堆内存空间的初始化\n",
    "- 初始化当前系统线程\n",
    "- 算法初始化（map、hash）\n",
    "- 加载命令行参数到 `os.Args`\n",
    "- 加载操作系统环境变量\n",
    "- 垃圾回收器的参数初始化\n",
    "- 设置 process 数量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 创建主协程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 创建一个新的协程, 执行`runtime.main`\n",
    "- 放入调度器等待调度"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 初始化M"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 初始化一个M, 用来调度主协程"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 主协程执行主函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://go.dev/src/runtime/proc.go"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```go\n",
    "// The main goroutine.\n",
    "func main() {\n",
    "  // ...\n",
    "\tfn := main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime\n",
    "\tfn()\n",
    "  // ...\n",
    "}...\n",
    "```\n",
    "\n",
    "- 执行 runtime 包中的 `init` 方法\n",
    "- 启动 GC 垃圾收集器\n",
    "- 执行 用户包依赖的 `init` 方法\n",
    "- 执行 用户主函数 `main.main()`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.5 Go语言是面向对象的吗"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://go.dev/doc/faq#Is_Go_an_object-oriented_language"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Go 允许 OO（面向对象）的编程风格\n",
    "- Go 的 `Struct` 可以看作其他语言的 `Class`\n",
    "- Go 缺乏其他语言的继承结构\n",
    "- Go的接口与其他语言有很大差异"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Go的\"类\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 在其他语言中，往往用 `class` 表示一类数据。\n",
    "- `class` 的每个实例称作“对象”。\n",
    "- 在 Go 中用 `struct` 表示一类数据。\n",
    "- `struct` 的每个实例并不是“对象”，而是此类类型的“值”。\n",
    "- `struct` 也可以定义方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Go的继承"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Go中没有继承关系\n",
    "- Go中使用组合代替继承\n",
    "- 组合中的匿名字段，通过语法糖达成了类似继承的效果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 定义一个基础结构（类似于基类）\n",
    "type Animal struct {\n",
    "\tName string\n",
    "}\n",
    "\n",
    "// 基础结构的方法（类似于基类的方法）\n",
    "func (a *Animal) Speak() {\n",
    "\tfmt.Printf(\"%s makes a sound.\\n\", a.Name)\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 定义一个派生结构（继承 Animal 的特性）\n",
    "type Dog struct {\n",
    "\tAnimal // 嵌套（类似于继承）\n",
    "\tBreed  string\n",
    "}\n",
    "\n",
    "// 子类重写方法（方法重载）\n",
    "func (d *Dog) Speak() {\n",
    "\tfmt.Printf(\"%s barks! Breed: %s\\n\", d.Name, d.Breed)\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Generic Animal makes a sound.\n",
      "Buddy barks! Breed: Golden Retriever\n",
      "Buddy makes a sound.\n"
     ]
    }
   ],
   "source": [
    "func main() {\n",
    "\t// 创建 Animal 实例\n",
    "\tanimal := Animal{Name: \"Generic Animal\"}\n",
    "\tanimal.Speak() // 输出: Generic Animal makes a sound.\n",
    "\n",
    "\t// 创建 Dog 实例\n",
    "\tdog := Dog{\n",
    "\t\tAnimal: Animal{Name: \"Buddy\"},\n",
    "\t\tBreed:  \"Golden Retriever\",\n",
    "\t}\n",
    "\tdog.Speak() // 输出: Buddy barks! Breed: Golden Retriever\n",
    "\n",
    "\t// 调用父类的方法\n",
    "\tdog.Animal.Speak() // 输出: Buddy makes a sound.\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Go的接口"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 接口可以定义 Go 中的一组行为相似的 `struct`。\n",
    "- `struct` 并不显式实现接口，而是隐式实现。\n",
    "- 通过以上手段去掉了面向对象中复杂而冗余的部分。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import \"fmt\"\n",
    "\n",
    "// 定义接口\n",
    "type Shape interface {\n",
    "\tArea() float64\n",
    "\tPerimeter() float64\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 实现接口的结构体：Rectangle\n",
    "type Rectangle struct {\n",
    "\tWidth, Height float64\n",
    "}\n",
    "\n",
    "func (r Rectangle) Area() float64 {\n",
    "\treturn r.Width * r.Height\n",
    "}\n",
    "\n",
    "func (r Rectangle) Perimeter() float64 {\n",
    "\treturn 2 * (r.Width + r.Height)\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 实现接口的结构体：Circle\n",
    "type Circle struct {\n",
    "\tRadius float64\n",
    "}\n",
    "\n",
    "func (c Circle) Area() float64 {\n",
    "\treturn 3.14 * c.Radius * c.Radius\n",
    "}\n",
    "\n",
    "func (c Circle) Perimeter() float64 {\n",
    "\treturn 2 * 3.14 * c.Radius\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Rectangle Area: 15.00, Perimeter: 16.00\n",
      "Circle Area: 50.24, Perimeter: 25.12\n"
     ]
    }
   ],
   "source": [
    "func main() {\n",
    "\t// 定义接口类型变量\n",
    "\tvar s Shape\n",
    "\n",
    "\t// 使用 Rectangle\n",
    "\ts = Rectangle{Width: 5, Height: 3}\n",
    "\tfmt.Printf(\"Rectangle Area: %.2f, Perimeter: %.2f\\n\", s.Area(), s.Perimeter())\n",
    "\n",
    "\t// 使用 Circle\n",
    "\ts = Circle{Radius: 4}\n",
    "\tfmt.Printf(\"Circle Area: %.2f, Perimeter: %.2f\\n\", s.Area(), s.Perimeter())\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.6 实战：企业级Go项目包管理方法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Go Modules"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 本质上，一个 Go 包 就是一个项目的源码。\n",
    "- `gomod` 的作用：将 Go 包 和 Git 项目 关联起来。\n",
    "- Go 包的版本 就是 Git 项目 的 Tag。\n",
    "- `gomod` 就是解决“需要哪个 Git 项目的什么版本”。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用 Modules"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```shell\n",
    "go get github.com/Jeffail/tunny\n",
    "```\n",
    "\n",
    "- 特定版本\n",
    "```shell\n",
    "go get github.com/Jeffail/tunny@0.1.3\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import \"github.com/Jeffail/tunny\"\n",
    "\n",
    "func main() {\n",
    "\ttunny.Pool{}\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "go: creating new go.mod: module usemodules\n"
     ]
    }
   ],
   "source": [
    "! cd ./3.6 && go mod init usemodules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "go: downloading github.com/Jeffail/tunny v0.1.4\n",
      "go: added github.com/Jeffail/tunny v0.1.4\n"
     ]
    }
   ],
   "source": [
    "! cd ./3.6 && go get github.com/Jeffail/tunny"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "module usemodules\n",
      "\n",
      "go 1.24.3\n",
      "\n",
      "require github.com/Jeffail/tunny v0.1.4 // indirect\n"
     ]
    }
   ],
   "source": [
    "! cd ./3.6 && cat go.mod"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用本地包文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "修改go.mod文件\n",
    "- `replace github.com/Jeffail/tunny => 本地文件路径`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`go vender`缓存到本地\n",
    "- `go build -mod vendor`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 创建Go Modules"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "module 地址路径/项目名字\n",
    "go 版本\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Go (gonb)",
   "language": "go",
   "name": "gonb"
  },
  "language_info": {
   "codemirror_mode": "",
   "file_extension": ".go",
   "mimetype": "text/x-go",
   "name": "go",
   "nbconvert_exporter": "",
   "pygments_lexer": "",
   "version": "go1.24.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
